package com.cam.iot.mqtt.handler;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.cam.iot.entity.IotHisData;
import com.cam.iot.entity.IotLiveData;
import com.cam.iot.service.IotDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

@Slf4j
@Component
public class MqttChannelHandler implements MessageHandler {

    @Autowired
    private IotDataService iotDataService;

    @Override
    public void handleMessage(Message<?> message) throws MessagingException {
        String topic = String.valueOf(message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
        String payload = String.valueOf(message.getPayload());
        log.info("接收到数据：{}", payload);
        if (!JSONUtil.isTypeJSON(payload)) {
            log.error("非JSON结构：{}", payload);
            return;
        }
        if (!payload.contains("ID") || !payload.contains("TYPE") || !payload.contains("TIME")) {
            log.error("关键数据缺失：{}", payload);
            return;
        }
        if (topic.contains("iot_his_data")) {
            try {
                this.saveHisData(payload);
            } catch (Exception e) {
                log.error("保存iot_his_data数据异常：{}", e.getMessage());
            }
        }

        if (topic.contains("iot_live_data")) {
            try {
                this.saveLiveData(payload);
            } catch (Exception e) {
                log.error("保存iot_live_data数据异常：{}", e.getMessage());
            }
        }
    }

    @Async
    @Transactional
    public void saveHisData(String message) {
        List<IotHisData> dataList = new ArrayList<>();
        JSONObject jsonObject = JSONUtil.parseObj(message);
        String deviceId = jsonObject.getStr("ID");
        Long timeStamp = jsonObject.getLong("TIME");
        LocalDateTime nowTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(timeStamp), ZoneId.systemDefault());

        List<String> factorCodeList = iotDataService.listFactorList();
        for (Map.Entry<String, Object> eachEntry : jsonObject.entrySet()) {
            if (factorCodeList.contains(eachEntry.getKey())) {
                IotHisData eachData = new IotHisData();
                eachData.setDeviceId(deviceId);
                eachData.setDatetime(Date.from(nowTime.atZone(ZoneId.systemDefault()).toInstant()));
                eachData.setFactorCode(eachEntry.getKey());
                eachData.setValue(eachEntry.getValue().toString());
                dataList.add(eachData);
            }
        }

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("year", nowTime.getYear());
        dataMap.put("month", String.format("%02d", nowTime.getMonthValue()));
        dataMap.put("dataList", dataList);
        iotDataService.insertHisDataMap(dataMap);

    }

    @Async
    @Transactional
    public void saveLiveData(String message) {
        List<IotLiveData> dataList = new ArrayList<>();
        JSONObject jsonObject = JSONUtil.parseObj(message);
        String deviceId = jsonObject.getStr("ID");
        Long timeStamp = jsonObject.getLong("TIME");
        List<String> factorCodeList = iotDataService.listFactorList();
        for (Map.Entry<String, Object> eachEntry : jsonObject.entrySet()) {
            if (factorCodeList.contains(eachEntry.getKey())) {
                IotLiveData eachData = new IotLiveData();
                eachData.setDeviceId(deviceId);
                eachData.setDatetime(Date.from(Instant.ofEpochSecond(timeStamp)));
                eachData.setFactorCode(eachEntry.getKey());
                eachData.setValue(eachEntry.getValue().toString());
                dataList.add(eachData);
            }
        }
        iotDataService.removeLiveDataByDeviceId(deviceId);
        iotDataService.insertLiveDataMap(dataList);
    }

}
